package com.hs.geek;

import java.io.*;

/**
 * @Author: songhao
 * @Date: 2021/8/3
 * @Description:
 *    自定义一个 Classloader，加载一个 Hello.xlass 文件，执行 hello 方法，
 *  此文件内容是一个 Hello.class 文件所有字节（x=255-x）处理后的文件。文件群里提供。
 */
public class MyClassLoader extends ClassLoader{

    private String classpath;
    private String extName;

    public MyClassLoader(String classpath, String extName) {
        this.classpath = classpath;
        this.extName = extName;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            //通过x=255-x转化回来
            byte[] classBytes = convertBytes(getData(name));
            if(classBytes != null){
                return defineClass(name,classBytes,0,classBytes.length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.findClass(name);
    }

    /**
     * 对字节信息进行转换
     * @param classBytes
     * @return
     */
    private byte[] convertBytes(byte[] classBytes){
        if(classBytes == null || classBytes.length == 0){
            return null;
        }
        byte[] newBytes = new byte[classBytes.length];
        for(int i = 0; i < classBytes.length; i++){
            newBytes[i] = (byte)(255 - (byte)(0xff & classBytes[i]));
        }
        return newBytes;
    }

    /**
     * 读取字节码文件
     * @param className
     * @return
     * @throws IOException
     */
    private byte[] getData(String className) throws IOException{
        InputStream in = null;
        ByteArrayOutputStream out = null;
        String path = classpath + File.separatorChar + className + this.extName;
        try {
            in = new FileInputStream(path);
            out = new ByteArrayOutputStream();
            byte[] buffer = new byte[2048];
            int len = 0;
            while((len = in.read(buffer)) != -1){
                out.write(buffer,0,len);
            }
            return out.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally{
            in.close();
            out.close();
        }
        return null;
    }
}
